package cn.yeziji.forum.dao.impl;

import cn.yeziji.forum.common.enums.ForumCommonStatus;
import cn.yeziji.forum.common.key.CommonKey;
import cn.yeziji.forum.dao.base.ForumTagsBaseDao;
import cn.yeziji.forum.dao.intf.ForumTagsDao;
import cn.yeziji.forum.dao.iquery.TagsQuery;
import cn.yeziji.forum.dto.tags.ForumTagsDTO;
import cn.yeziji.forum.entity.ForumDetailsEntity;
import cn.yeziji.forum.entity.ForumTagsEntity;
import cn.yeziji.forum.exception.ForumException;
import cn.yeziji.forum.exception.TagException;
import cn.yeziji.forum.mapper.ForumTagsMapper;
import cn.yeziji.forum.common.enums.status.TagStatus;
import cn.yeziji.forum.utils.ListsCollect;
import cn.yeziji.forum.utils.StrUtils;
import io.jsonwebtoken.lang.Collections;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 标签逻辑实现层
 *
 * @author gzkemays
 * @since 2021/12/21 15:54
 */
@Repository
public class ForumTagsDaoImpl extends ForumTagsBaseDao implements ForumTagsDao {
  @Resource ForumTagsMapper tagsMapper;

  @Override
  @Transactional(rollbackFor = {TagException.class})
  public int insertByDetail(ForumDetailsEntity details) {
    String tagsStr = details.getTags().toLowerCase(Locale.ROOT);
    List<String> tags = StrUtils.strToList(tagsStr, CommonKey.LIST_STR_SPILT, String.class);
    if (!tags.isEmpty()) {
      List<String> sqlTags = tagsMapper.listObjs(TagsQuery.selectTagsByInTags(tags));
      if (!Collections.isEmpty(sqlTags)) {
        List<ForumTagsEntity> collect =
            sqlTags.stream()
                .filter(tag -> !tags.contains(tag))
                .map(this::getEntityByTags)
                .distinct()
                .collect(Collectors.toList());
        if (!collect.isEmpty()) {
          return tagsMapper.insertBatch(collect);
        }
      } else {
        List<ForumTagsEntity> collect =
            tags.stream().map(this::getEntityByTags).distinct().collect(Collectors.toList());
        return tagsMapper.insertBatch(collect);
      }
    }
    return 0;
  }

  @Override
  public List<String> getTags(ForumTagsDTO dto) {
    return ListsCollect.of(
            tagsMapper.listPoJos(TagsQuery.selectTagsSize(dto), map -> map.get("tags").toString()))
        .orElseThrow(() -> new TagException(TagStatus.TAG_NOT_FOUND));
  }

  @Override
  public List<String> getTagsByNickname(String nickname) {
    if (StringUtils.isBlank(nickname)) {
      throw new ForumException(ForumCommonStatus.DATA_ERROR);
    }
    return ListsCollect.of(
            tagsMapper.listPoJos(
                TagsQuery.selectTagsByNicknameDetails(nickname), map -> map.get("tags").toString()))
        .orElseEmpty();
  }

  private ForumTagsEntity getEntityByTags(String tag) {
    String regEx = "[`~!@#$%^&*()+=|{}:;\\\\[\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？']";
    Matcher matcher = Pattern.compile(regEx).matcher(tag);
    if (matcher.matches()) {
      throw new TagException(TagStatus.TAG_HAS_NOT_ALLOW_SYMBOL);
    }
    ForumTagsEntity entity = new ForumTagsEntity();
    entity.setTags(tag);
    return entity;
  }
}
